package org.zizi.db.plan;

import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.zizi.db.charset.CharsetEncoder;
import org.zizi.db.column.ColumnReader;
import org.zizi.db.plan.reader.ArrayResultReader;
import org.zizi.db.plan.reader.BeanResultReader;
import org.zizi.db.plan.reader.ListResultReader;
import org.zizi.db.plan.reader.MapResultReader;
import org.zizi.db.plan.reader.PrimitiveResultReader;

public abstract class ResultPlan
{
	private static Set<Class<?>> primitives = new HashSet<Class<?>>();
	static
	{
		primitives.add(Integer.class);
		primitives.add(Integer.TYPE);
		primitives.add(Long.class);
		primitives.add(Long.TYPE);
		primitives.add(Double.class);
		primitives.add(Double.TYPE);
		primitives.add(Boolean.class);
		primitives.add(Boolean.TYPE);
		primitives.add(Date.class);
		primitives.add(String.class);
		primitives.add(byte[].class);
	}
	
	protected CharsetEncoder charset;
	
	protected ResultPlan(CharsetEncoder charset)
	{
		this.charset = charset;
	}
	
	protected abstract ColumnReader getColumnReader(int type);
	
	public <T> ResultReader<T> getResultReader(Class<T> type, ResultSetMetaData meta) throws Exception
	{
		if (primitives.contains(type))	//如果是单值类型
		{
			int t = meta.getColumnType(1);
			
			ColumnReader reader = getColumnReader(t);
			if (reader == null) throw new Exception("不支持的数据列类型: " + t);
			
			return new PrimitiveResultReader<T>(type, reader);
		}
		else if (List.class.equals(type)) //List 类型
		{
			List<ColumnReader> readers = new ArrayList<ColumnReader>();
			
			int n = meta.getColumnCount();
			for (int i = 0; i < n; i++)
			{
				int t = meta.getColumnType(i + 1);
				
				ColumnReader reader = getColumnReader(t);
				if (reader == null) throw new Exception("不支持的数据列类型: " + t);
				
				readers.add(reader);
			}
			
			return new ListResultReader<T>(type, readers);
		}
		else if (Map.class.equals(type)) //Map 类型
		{
			List<String> columns = new ArrayList<String>();
			List<ColumnReader> readers = new ArrayList<ColumnReader>();
			
			int n = meta.getColumnCount();
			for (int i = 0; i < n; i++)
			{
				int t = meta.getColumnType(i + 1);
				
				ColumnReader reader = getColumnReader(t);
				if (reader == null) throw new Exception("不支持的数据列类型: " + t);
				
				columns.add(meta.getColumnName(i + 1));
				readers.add(reader);
			}
			
			return new MapResultReader<T>(type, columns, readers);
		}
		else if (Object[].class.equals(type)) //Array 类型
		{
			int n = meta.getColumnCount();
			ColumnReader[] readers = new ColumnReader[n];
			
			for (int i = 0; i < n; i++)
			{
				int t = meta.getColumnType(i + 1);
				
				ColumnReader reader = getColumnReader(t);
				if (reader == null) throw new Exception("不支持的数据列类型: " + t);
				
				readers[i] = reader;
			}
			
			return new ArrayResultReader<T>(type, readers);
		}
		else	//Bean类型
		{
			List<String> columns = new ArrayList<String>();
			List<ColumnReader> readers = new ArrayList<ColumnReader>();
			
			int n = meta.getColumnCount();
			for (int i = 0; i < n; i++)
			{
				int t = meta.getColumnType(i + 1);
				
				ColumnReader reader = getColumnReader(t);
				if (reader == null) throw new Exception("不支持的数据列类型: " + t);
				
				columns.add(meta.getColumnName(i + 1));
				readers.add(reader);
			}
			
			return new BeanResultReader<T>(type, columns, readers);
		}
	}
}
